package uk.ac.cam.cl.projectcharlie2010.game.player.physical;

import uk.ac.cam.cl.projectcharlie2010.camera.Camera;
import uk.ac.cam.cl.projectcharlie2010.game.player.Player;
import ch.nostromo.tiffanys.game.move.MoveInput;


public class PlayerPhysical extends Player {

	private String name;
	private PhysicalPlayerListener desktopController;
	private boolean active = true;
	private Thread runner;
	
	private VisualMoveRecogniser visualMoveRecogniser;

	public static VisualMoveRecogniser getLiveVisualMoveReconiser() {
		
		//return new FakePopUpVMR(); //TESTING ONLY
		
		return Camera.getLiveInstance();
	}
	
	//NOT CLEAN!
	public static void updateBackgroundForMoveRecognition(){
		Camera.getInstance().updateBackgroundCeiling();
	}
	
	//NOT CLEAN!
	public static void calibrateVisualMoveRecogniser(){
		Camera.getInstance().calibrate();
	}
	
	@Override
	public PlayerPhysical clone() throws CloneNotSupportedException {
		PlayerPhysical result = (PlayerPhysical) super.clone();
		result.name = name;
		result.desktopController = desktopController;
		result.active = true;
		return result;
	}


	public PlayerPhysical(String name, PhysicalPlayerListener desktopController) {
		this.name = name;
		this.desktopController = desktopController;
	}

	@Override
	public String getPlayerName() {
		return name;
	}

	public synchronized void seeNextMove() throws VisualCalibrationException {
		
		if (visualMoveRecogniser == null) {
			visualMoveRecogniser = getLiveVisualMoveReconiser(); //SIDE EFFECT! Sets the visual move recogniser to LIVE
		}
		
		if (!visualMoveRecogniser.isCalibrated()) {
			throw new VisualCalibrationException();
		}

		runner = new Thread() {

			@Override
			public void run() {
				
				synchronized (runner) {
					if (!active) {
						try {
							System.out.println("waiting in PhysicalPlayer");
							runner.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}

				try {
					MoveInput move = visualMoveRecogniser.seeNextMove();
					
					//FIXME Should this wait check be here?
					synchronized (runner) {
						if (!active) {
							try {
								System.out.println("waiting in PhysicalPlayer");
								runner.wait();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
					
					
					desktopController.seeNextMoveFinished(move);
				} catch (ImpossibleMoveException e) {
					desktopController.seeNextMoveFailed();	
				} catch (AbortedException e) {
					//TODO RAT - then just ignore if this exception occurs
					System.out.println("Move recognition aborted");
				}
			}

		};

		runner.start();
	}


	@Override
	public void setActive(boolean active) {
		
		if (active && runner != null)  {
			synchronized (runner) {
				runner.notifyAll();
			}
		}
		this.active = active;
	}


	@Override
	public void kill() {
		if (visualMoveRecogniser != null) {
			visualMoveRecogniser.kill();
		}
	}

}
